#pragma once
#include <iostream>
#include <queue>
#include <vector>
#include <unistd.h>
#include "mutex.hpp"
#include "cond.hpp"
#include "Thread.hpp"
using namespace std;

const static int defaultthreadnum = 3;
template <typename T>
class ThreadPool
{
private:
    bool Empty()
    {
        return _q.empty();
    }
    void Routine(const std::string &name)

    {
        while (true)
        {

            T t;
            while (QueueIsEmpty() && _is_running)
            // 线程池正在运行，然后任务队列0，进入等到，等到了任务之后，获得锁，等待的数--
            {
                _wait_thread_num++;
                _cond.Wait(_lock);
                _wait_thread_num--;
            }
            t = _q.front();
        }
    }

public:
    ThreadPool(int threadnum = defaultthreadnum)
        : _threadnum(threadnum), _is_running(false), _wait_thread_num(0)
    {
        // 然后创建一个个的进程
        for (int i = 0; i < _threadnum; i++)
        {
            // 每一个进程的名字
            sting name = "线程" + to_string(i + 1);
            // 把每一个的进程push进去
            // 一个问题push系列的接口和emplace的接口有什么区别
            // 匿名函数lambda            函数参数             函数主体
            _thread.emplace_back([this](const string &name)
                                 { this->Routine(name) }, name);
           
        }
         LOG(LogLevel::INFO) << "thread pool obj create success";
    }
    

        void Start()
        {
            if (_is_running)
                return;
            _is_running = true;
            for (auto &t : _threads)
            {
                t.Start();
            }
            LOG(LogLevel::INFO) << "thread pool running success";
        }
    // 线程池退出的逻辑是什么
    // 1 如果被唤醒 and 任务队列没有任务=让线程推迟
    // 2 如果被唤醒 and 任务队列有任务 =让线程执行完任务再退出
    // 3 本身没有休眠 我们让吧任务队列的任务执行完再退出
    //  3和2 其实是一种情况 因为有任务线程是不会休眠的
    void Stop()
    {
        if (!_is_running)
            return;          // 没有在运行直接退出
        _is_running = false; // 在运行把退出设置为false
        if (_wait_thread_num)
            _cond.NotifyAll(); // 如果等待队列里面有任务，就唤醒所有的进程
    }
    void Wait()
    {
        for (auto &t : _threads)
        {
            t.Join();
        }
        LOG(LogLevel::INFO) << "thread pool wait success";
    }
    void Enqueue(const T &t)
    {
        if (!_is_running)
            return;
        {
            LockGuard lockguard(&_lock);

            _q.push(t);
            if (_wait_thread_num > 0)
                _cond.NotifyOne();
        }
    }

    ~ThreadPool()
    {
    }

    // 任务队列
    // 多个线程
    // queue<T> _q;
    // vector<Thread> _threads // 1.创建线程对象，2.让线程对象启动
    //     int _threadnum;     // 线程个数
    // int _wait_thread_num;   // 正在等待的线程个数

private:
    queue<T> _q; // 整体使用的临界资源

    // 多个线程
    vector<Thread> _threads; // 1. 创建线程对象 2. 让线程对象启动
    int _threadnum;
    int _wait_thread_num;
    // 保护机制
    Mutex _lock;
    Cond _cond; // 等待队列

    // 是否正在运行
    bool _is_running;
};
